package default_package;

import java.io.IOException;
import java.net.ServerSocket;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.TreeMap;



import default_package.Utilisateur.Statut;


public class Controleur {
	private TreeMap<Integer, ThreadClient> threads;
	
	private TreeMap<String, Utilisateur> users;
	
	private ArrayList<Langue> langues;
	
	private ServerSocket socket;
	private ServerSocket socket_son;
	private ServerSocket socket_confirm;
	private ServerSocket socket_sound;
	
	
	
	private GregorianCalendar calendar;
	private Connection cn=null;
	
	private int id;
	
	
	public Controleur() {
		id = 0;
		String url = "jdbc:mysql://mysql1.alwaysdata.com/mestest_pt";
		//"jdbc:mysql://projet-tut-info-1/benazizf";
		String login = "mestest_user_pt" ;//"benazizf";
		String password = "pt2a" ;//"benazizf";
		setUsers(new TreeMap<String, Utilisateur>());
		setLangues(new ArrayList<Langue>());
		try {
			
			// Etape 1 : Chargement du driver

			Class.forName("com.mysql.jdbc.Driver");
		
			// Etape 2 : récupération de la connexion

			cn = DriverManager.getConnection(url, login, password);
			
			restaure();
			
			
			setThreads(new TreeMap<Integer, ThreadClient>());
			setDate(new GregorianCalendar());
			System.out.println(getDate().get(GregorianCalendar.YEAR) + "/" + (getDate().get(GregorianCalendar.MONTH) +1) + "/" + getDate().get(GregorianCalendar.DAY_OF_MONTH) + " " + getDate().get(GregorianCalendar.HOUR_OF_DAY) + ":" + getDate().get(GregorianCalendar.MINUTE));
			
			System.out.println("Serveur OK, version 1.14");
			socket = new ServerSocket(2009);
			socket_son = new ServerSocket(2010);
			socket_confirm = new ServerSocket(2011);
			socket_sound = new ServerSocket(2012);
			socket_sound.setPerformancePreferences(0, 2, 1);


			while(true) {
			//	Thread t = new Thread(new ThreadClient(socket.accept(), this, getThreads().size()));
				Thread t = new Thread(new ThreadClient(socket.accept(), socket_son.accept(), socket_confirm.accept(), socket_sound.accept(), this, getThreads().size()));
				t.start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
	
	public Connection getCn()
	{
		return cn;
	}
	
	private ArrayList<Langue> getLangues() {
		return langues;
	}

	private void setLangues(ArrayList<Langue> langues) {
		this.langues = langues;
	}
	
	public Langue getLangues(int index) {
		return langues.get(index);
	}
	
	public Langue getLangues(String l) {
		Langue retour = null;
		for(int i = 0; i < getLangues().size(); i++) {
			if(getLangues(i).getNom().equals(l)) {
				retour = getLangues(i);
			}
		}
		return retour;
	}

	public int setLangues(Langue l) {
		int taille = langues.size();
		langues.add(l);
		return taille;
	}

	public GregorianCalendar getDate() {
		return calendar;
	}
	
	public void setDate(GregorianCalendar d) {
		this.calendar = d;
	}

	private TreeMap<Integer, ThreadClient> getThreads() {
		return threads;
	}

	private void setThreads(TreeMap<Integer, ThreadClient> threads) {
		this.threads = threads;
	}
	
	public int setThreads(ThreadClient t) {
		int max = 0;
		for(ThreadClient th : getThreads().values()) {
			if(max < th.getNumThread()) {
				max = th.getNumThread();
			}
		}
		int numThread = max + 1;
		getThreads().put(numThread, t);
		return numThread;
	}
	
	public void removeThread(ThreadClient t) {
		getThreads().remove(t.getNumThread());
	}
	
	public ThreadClient getThread(int numThread) {
		return getThreads().get(numThread);
	}
	
	public ThreadClient getThreadParClient(String login) {
		ThreadClient retour = null;
		for(ThreadClient t : getThreads().values()) {
			if(t.getUser().getLogin().equals(login)) {
				retour = t;
			}
		}
		return retour;
	}

	public TreeMap<String, Utilisateur> getUsers() {
		return users;
	}
	
	/**
	 * Methode permettant de connaitre tous les utilisateurs qui sont connectes
	 * @return une TreeMap d'utilisateur connecte indexee sur le login
	 */
	public TreeMap<String, Utilisateur> getUsersConnected() {
		TreeMap<String, Utilisateur> tmp = new TreeMap<String, Utilisateur>();
		for(Utilisateur u : getUsers().values()) {
			if(!u.getStatut().equals(Statut.Hors_Ligne)) {
				tmp.put(u.getLogin().toLowerCase(), u);
			}
		}
		return tmp;
	}

	private void setUsers(TreeMap<String, Utilisateur> users) {
		this.users = users;
	}
	
	public Utilisateur getUser(String login) {
		return getUsers().get(login.toLowerCase());
	}
	
	
	public void setUser(Utilisateur user) throws UtilisateurExisteDejaException {
		if (getUser(user.getLogin()) == null) {
			getUsers().put(user.getLogin().toLowerCase(), user);
			user.sauver(cn);
		} else {
			throw new UtilisateurExisteDejaException();
		}
	}
	
	public void updateUser(Utilisateur user) {
			user.update(cn);
	}
	
	public int nextFreeId() {
		id++;
		return id;
	}
	public int getId() {
		return id;
	}
	
	private void restaure()
	{
		Statement st=null; 
		ResultSet rs =null;
		Utilisateur user = null;
		try {
			st = cn.createStatement();
			
			
			
			String sql = "SELECT * FROM Compte";

			rs = st.executeQuery(sql);
			
			while (rs.next()) {
				user = new Utilisateur(rs.getString("login"),rs.getString("mdp"),
						rs.getString("nom"),rs.getString("prenom"),rs.getString("sexe"),rs.getString("type"),rs.getString("nationalite"));
				users.put(user.getLogin().toLowerCase(), user);
			}
			
			
			sql = "SELECT * FROM Langues ORDER BY nomLangue";

			rs = st.executeQuery(sql);
			Langue l = null;
			while (rs.next()) {
				l = new Langue(rs.getString("nomLangue"));
				langues.add(l);
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
